<?php
/**
 * FP_Profile class file
 * @package FlickrPhotosets
 */

/**
 * This class handles the gathering and preparation of data for constructing
 * the profile box.
 * 
 * @package FlickrPhotosets
 * @author Brad Dougherty <bdougherty@gmail.com>
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License 3.0
 */
class FP_Profile extends FlickrPhotosets {
	
	/**
	 * The size of the photo to render.
	 * @var string
	 */
	public $photo_size;
	
	/**
	 * The array of photos to show.
	 * @var array
	 */
	public $photos = array();
	
	/**
	 * Whether this is preview mode.
	 * @var boolean
	 */
	public $preview_mode;
	
	/**
	 * Contains strings for displaying the profile.
	 * @var array
	 */
	public $profile;
	
	/**
	 * The sort information.
	 * @var array
	 */
	public $sort = array();
	
	/**
	 * Gets the user's id, figures out whether to operate in preview mode,
	 * and initializes.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	public function __construct() {
		parent::__construct();
		
		// Get the uid from the handle
		$this->uid = $_GET['handle'];
		
		// Set this to preview mode
		$this->preview_mode = (isset($_GET['preview'])) ? true : false;
		
		// Initialize
		$this->init_profile();
	}
	
	/**
	 * Gets the configuration from the post variables if operating in
	 * preview mode.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	private function get_post_config() {
		if ($this->preview_mode) {
			$this->config['profile_display'] = $_REQUEST['profile_display'];
			$this->config['profile_count']   = $_REQUEST['profile_count'];
			$this->config['profile_tags']    = $_REQUEST['profile_tags'];
			$this->config['profile_tagmode'] = $_REQUEST['profile_tagmode'];
			$this->config['profile_sort']    = $_REQUEST['profile_sort'];
		}
	}
	
	/**
	 * Set strings that are related to the sort field.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	private function get_sort_info() {
		if ($this->config['profile_sort'] == $this->profile_sort['date_posted_desc']) {
			$this->sort['param'] = 'date-posted-desc';
			$this->sort['string'] = 'last';
			$this->sort['type'] = 'posted';
		}
		else if ($this->config['profile_sort'] == $this->profile_sort['date_posted_asc']) {
			$this->sort['param'] = 'date-posted-asc';
			$this->sort['string'] = 'first';
			$this->sort['type'] = 'posted';
		}
		else if ($this->config['profile_sort'] == $this->profile_sort['date_taken_desc']) {
			$this->sort['param'] = 'date-taken-desc';
			$this->sort['string'] = 'last';
			$this->sort['type'] = 'taken';
		}
		else if ($this->config['profile_sort'] == $this->profile_sort['date_taken_asc']) {
			$this->sort['param'] = 'date-taken-asc';
			$this->sort['string'] = 'first';
			$this->sort['type'] = 'taken';
		}
		else if ($this->config['profile_sort'] == $this->profile_sort['interesting_desc']) {
			$this->sort['param'] = 'interestingness-desc';
			$this->sort['string'] = 'last';
			$this->sort['type'] = 'most interesting';
		}
		else if ($this->config['profile_sort'] == $this->profile_sort['interesting_asc']) {
			$this->sort['param'] = 'interestingness-asc';
			$this->sort['string'] = 'last';
			$this->sort['type'] = 'least interesting';
		}
	}
	
	/**
	 * Returns a string of the tags applied. Each tag links to the
	 * appropriate page on Flickr.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 * @return False if no tags are being used, the string otherwise
	 */
	private function get_tag_string() {
		if (!empty($this->config['profile_tags'])) {
			
			$split = explode(",", $this->config['profile_tags']);
			$tag_array = array();
			foreach ($split as $tag) {
				$tag = trim($tag);
				array_push($tag_array, '<a href="'.$this->flickr->urls_getUserPhotos($this->nsid).'tags/'.$tag.'/">'.$tag.'</a>');
			}
			
			$tag_string = (count($tag_array) > 1) ? 'with tags ' : 'with tag ';
			$tag_string .= implode(', ', $tag_array);
			
			return $tag_string;
			
		}
		else {
			return false;
		}
	}
	
	/**
	 * Gets the user's configuration information, initializes the Flickr
	 * object and runs the proper preparation method.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	private function init_profile() {
		
		// Get the configuration
		$this->get_info();
		$this->get_post_config();
				
		// Initialize Flickr
		$this->init_flickr(false, true, false);
		//$this->flickr_user = $this->flickr->people_getInfo($this->nsid);
		
		// Set the tag mode properly
		$this->config['profile_tagmode'] = ($this->config['profile_tagmode'] == $this->profile_tagmode['any']) ? 'any' : 'all';
		
		// Prepare the profile depending on the display
		if ($this->config['profile_display'] == $this->profile_display['sets'] or $this->config['profile_display'] == $this->profile_display['random_sets']) {
			$this->prepare_sets();
		}
		else if ($this->config['profile_display'] == $this->profile_display['overview']) {
			$this->prepare_overview();
		}
		else {
			$this->prepare_photos();
		}
		
		// Use a bigger size if there is only one photo.
		if (count($this->photos['photo']) == 1 and $this->config['profile_display'] != $this->profile_display['sets']) {
			$this->photo_size = 'small';
		}
		else {
			$this->photo_size = 'square';
		}
		
	}
	
	/**
	 * Prepares the information if displaying photos.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	private function prepare_photos() {
		
		$this->get_sort_info();
		
		/*
		Showing most recent photos
		*/
		if ($this->config['profile_display'] == $this->profile_display['last']) {
			
			// Get the last 100 photos
			$page = 1;
			$this->photos = $this->flickr->photos_search(array(
				'user_id' => $this->nsid,
				'tags' => $this->config['profile_tags'],
				'tag_mode' => $this->config['profile_tagmode'],
				'sort' => $this->sort['param'],
				'page' => $page
			));
			
			// Remove photos that don't match the privacy settings
			$this->photos['photo'] = $this->remove_photos($this->photos['photo']);
			
			// If we don't find any eligible photos, keep getting the next 100 until we find enough
			/*
			
			THIS IS INFINITELY LOOPING UNDER CERTAIN CIRCUMSTANCES!!!!!
			If there aren't enough photos, it keeps looping forever.
			Should be OK if we keep it from getting to the while if there is only one page of results
			
			*/
			$count = count($this->photos['photo']);
			while ($count < $this->config['profile_count'] and ($this->photos['pages'] - $this->photos['page']) > 1) {
				
				// Get the next page
				$page++;
				$photos = $this->flickr->photos_search(array(
					'user_id' => $this->nsid,
					'tags' => $this->config['profile_tags'],
					'tag_mode' => $this->config['profile_tagmode'],
					'sort' => $this->sort['param'],
					'page' => $page
				));
				$pages = $photos['pages'];
				$this->echo_debug('Getting page ', $page, ' of ', $pages);
				
				// Remove photos that don't match the privacy setting
				$photos['photo'] = $this->remove_photos($photos['photo']);
				
				// Add any eligible photos to the main array
				$this->photos['photo'] = array_merge($this->photos['photo'], $photos['photo']);
				
				// Recalculate the count
				$count = count($this->photos['photo']);
				$this->echo_debug('There are ', $count, ' photos eligible for display');
				
			}
			
			// If there are no photos, show an error
			if (count($this->photos['photo']) < 1) {
				$this->error(FP_Error::$profile_no_photos);
			}
			
			// Slice the photos down to however many they want to display
			// i think this fails if the number of photos returned is less than the number they want
			$this->photos['photo'] = array_slice($this->photos['photo'], 0, $this->config['profile_count']);
			
			// Set the subtitle string
			if ($this->config['profile_sort'] == $this->profile_sort['interesting_desc'] or $this->config['profile_sort'] == $this->profile_sort['interesting_asc']) {
				$this->profile['subtitle'] = 'Showing the ';
				$this->profile['subtitle'] .= ($this->config['profile_count'] == 1) ? ' ' : $this->config['profile_count'].' ';
				$this->profile['subtitle'] .= $this->sort['type'].' ';
				$this->profile['subtitle'] .= (count($this->photos['photo']) == 1) ? 'photo' : 'photos';
			}
			else {
				$this->profile['subtitle'] = 'Showing the '.$this->sort['string'].' ';
				$this->profile['subtitle'] .= ($this->config['profile_count'] == 1) ? ' ' : $this->config['profile_count'].' ';
				$this->profile['subtitle'] .= (count($this->photos['photo']) == 1) ? 'photo' : 'photos';
				$this->profile['subtitle'] .= ' '.$this->sort['type'];
			}
			
			
		}
		/*
		Showing faily recent photos
		*/
		else if ($this->config['profile_display'] == $this->profile_display['recent']) {
			
			/*
			We need to set the sort to be descending so that we actually
			get recent photos!
			*/
			$reverse = false;
			if ($this->config['profile_sort'] == $this->profile_sort['date_posted_asc']) {
				$this->sort['param'] = 'date-posted-desc';
				$reverse = true;
			}
			else if ($this->config['profile_sort'] == $this->profile_sort['date_taken_asc']) {
				$this->sort['param'] = 'date-taken-desc';
				$reverse = true;
			}

			// Calculate the number of photos per page
			$photos_to_get = $this->config['profile_count'] * 15;
			$photos_to_get = ($photos_to_get > $this->flickr_user['photos']['count']) ? $this->flickr_user['photos']['count'] : $photos_to_get;

			// Retrieve the last $config['profile_count'] * 15 photos
			$photo_query = $this->flickr->photos_search(array(
				'user_id' => $this->nsid,
				'tags' => $this->config['profile_tags'],
				'tag_mode' => $this->config['profile_tagmode'],
				'sort' => $this->sort['param'],
				'per_page' => $photos_to_get,
			));
			
			// Remove photos that don't match the privacy settings
			$photo_query['photo'] = $this->remove_photos($photo_query['photo']);

			// If there are no photos, show an error
			if (count($photo_query['photo']) < 1) {
				$this->error(FP_Error::$profile_no_photos);
			}

			// Pick out the desired number of random photos
			if (count($photo_query['photo']) > $this->config['profile_count']) {
				$photos_rand = array_rand($photo_query['photo'], $this->config['profile_count']);
			}
			else if (count($photo_query['photo']) == $this->config['profile_count']) {
				$photos_rand = $photo_query['photo'];
			}
			else {
				$this->error(FP_Error::$profile_no_photos);
			}
			
			// Create our photos['photo'] array
			if (count($photos_rand) > 1) {
				for ($i = 0; $i < count($photos_rand); $i++) {
					$this->photos['photo'][$i] = $photo_query['photo'][$photos_rand[$i]];
				}
			}
			else {
				$this->photos['photo'][0] = $photo_query['photo'][$photos_rand];
			}

			// Reverse the array if sorting ascending
			if ($reverse) {
				$this->photos['photo'] = array_reverse($this->photos['photo'], true);
			}
			
			// Set the subtitle string
			$this->profile['subtitle'] = 'Showing '.$this->config['profile_count'].' recent ';
			$this->profile['subtitle'] .= (count($this->photos['photo']) == 1) ? 'photo' : 'photos';
			$this->profile['subtitle'] .= ($this->sort['string'] == 'first') ? ', oldest first' : '';
			
		}
		/*
		Showing random photos
		*/
		else if ($this->config['profile_display'] == $this->profile_display['random']) {
			
			/*
			We need to set the sort to be descending so that we can get
			all of the user's photos
			*/
			$reverse = false;
			if ($this->config['profile_sort'] == $this->profile_sort['date_posted_asc']) {
				$this->sort['param'] = 'date-posted-desc';
				$reverse = true;
			}
			else if ($this->config['profile_sort'] == $this->profile_sort['date_taken_asc']) {
				$this->sort['param'] = 'date-taken-desc';
				$reverse = true;
			}
			
			// Calculate the number of photos per page
			$photos_to_get = 500;
			$photos_to_get = ($photos_to_get > $this->flickr_user['photos']['count']) ? $this->flickr_user['photos']['count'] : $photos_to_get;
			if ($this->config['profile_sort'] == $this->profile_sort['interestingness_desc']) {
				$photos_to_get = 150;
			}

			// Retrieve the last 500 photos
			$photo_query = $this->flickr->photos_search(array(
				'user_id' => $this->nsid,
				'tags' => $this->config['profile_tags'],
				'tag_mode' => $this->config['profile_tagmode'],
				'sort' => $this->sort['param'],
				'per_page' => $photos_to_get,
			));
			
			// If there are no photos, show an error
			if (count($photo_query['photo']) < 1) {
				$this->error(FP_Error::$profile_no_photos);
			}
			
			// Find out how many more pages we need to call and call them
			$pages_to_call = $photo_query['pages']-1;
			if ($pages_to_call > 0) {
				for ($i = 0; $i < $pages_to_call; $i++) {

					$additional_photos = $this->flickr->photos_search(array(
						'user_id' => $this->nsid,
						'tags' => $this->config['profile_tags'],
						'tag_mode' => $this->config['profile_tagmode'],
						'sort' => $this->sort['param'],
						'per_page' => $photos_to_get,
						'page' => ($i+2),
					));

					// Merge this array with the rest
					$photo_query['photo'] = array_merge($photo_query['photo'], $additional_photos['photo']);

				}
			}
			
			// Remove photos that don't match the privacy settings
			$photo_query['photo'] = $this->remove_photos($photo_query['photo']);
			
			// If there are no photos, show an error
			if (count($photo_query['photo']) < 1) {
				$this->error(FP_Error::$profile_no_photos);
			}
			
			// Pick out the desired number of random photos
			$photos_rand = array_rand($photo_query['photo'], $this->config['profile_count']);

			// Create our photos['photo'] array
			$photos_rand_count = count($photos_rand);
			if ($photos_rand_count > 1) {
				for ($i = 0; $i < $photos_rand_count; $i++) {
					$this->photos['photo'][$i] = $photo_query['photo'][$photos_rand[$i]];
				}
			}
			else {
				$this->photos['photo'][0] = $photo_query['photo'][$photos_rand];
			}
			
			// Reverse the array if sorting ascending
			if ($reverse) {
				$this->photos['photo'] = array_reverse($this->photos['photo'], true);
			}
			
			// Set the subtitle string
			$this->profile['subtitle'] = 'Showing '.$this->config['profile_count'].' random ';
			$this->profile['subtitle'] .= (count($this->photos['photo']) == 1) ? 'photo' : 'photos';
			$this->profile['subtitle'] .= ($this->sort['string'] == 'first') ? ', oldest first' : '';
			
		}
		
		// See all url
		$this->profile['see_all_url'] = $this->canvas_url.'/photos/'.$this->uid.'/';
		
		// Append tags to the subtitle string
		$this->profile['subtitle'] .= ' '.$this->get_tag_string();
		
	}
	
	/**
	 * Prepares the information if displaying an overview.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	private function prepare_overview() {
		// Create display strings
		$this->profile['see_all_url'] = $this->canvas_url.'/photos/'.$this->uid.'/sets/';
		$this->profile['subtitle'] = $this->get_name_fbml(false, true, false).' Flickr Account';
	}
	
	/**
	 * Prepares the information if displaying sets.
	 * 
	 * @author Brad Dougherty <bdougherty@gmail.com>
	 */
	private function prepare_sets() {
				
		// Get the user's sets
		$photosets = $this->flickr->photosets_getList($this->nsid);
		
		// If there are no photosets, show an error
		if (count($photosets['photoset']) < 1) {
			$this->error(FP_Error::$profile_no_photosets);
		}
		
		// Make sure the config count isn't greater than the number of sets
		if ($this->config['profile_count'] > count($photosets['photoset'])) {
			$this->config['profile_count'] = count($photosets['photoset']);
		}
		
		// Randomize
		if ($this->config['profile_display'] == $this->profile_display['random_sets']) {
			shuffle($photosets['photoset']);
		}
		
		/*
		Add the primary photos of each set to the photos array.
		Also include the set information.
		*/
		for ($i = 0; $i < $this->config['profile_count']; $i++) {
			$this->photos['photo'][$i] = $this->flickr->photos_getInfo($photosets['photoset'][$i]['primary']);
			$this->photos['photo'][$i]['set']['id'] = $photosets['photoset'][$i]['id'];
			$this->photos['photo'][$i]['set']['title'] = $photosets['photoset'][$i]['title'];
			$this->photos['photo'][$i]['set']['photos'] = $photosets['photoset'][$i]['photos'];
		}
		
		// Create display strings
		$this->profile['see_all_url'] = $this->canvas_url.'/photos/'.$this->uid.'/sets/';
		$this->profile['subtitle'] = 'Showing '.$this->config['profile_count'].' ';
		$this->profile['subtitle'] .= ($this->config['profile_display'] == $this->profile_display['random_sets']) ? 'random ' : '';
		$this->profile['subtitle'] .= (count($this->photos['photo']) == 1) ? 'set' : 'sets';
		
	}
	
}

?>